home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / sparc.lha / sparc / dynload.c next >
C/C++ Source or Header  |  1991-08-14  |  11KB  |  406 lines

  1. /*
  2.  *            D Y N L O A D . C 
  3.  *
  4.  * This file contains functions to help dynamically load foreign UNIX files
  5.  * into a running T process.
  6.  *
  7.  * written by Dorab Patel <dorab@neptune.cs.ucla.edu>
  8.  * December 24, 1986
  9.  * Copyright Dorab Patel (C) 1986
  10.  * Permission is given to distribute this software free to anyone
  11.  * using it for a non-commercial purpose. Comments/bug reports/fixes
  12.  * are encouraged.
  13.  *
  14.  * $Revision: 1.1 $
  15.  *
  16.  * $Log:    dynload.c,v $
  17.  * Revision 1.1  86/12/24  18:20:44  dorab
  18.  * Initial Revision
  19.  * 
  20.  */
  21. #ifndef lint
  22. static char RCSid[] = "@(#)$Header: dynload.c,v 1.1 86/12/24 18:20:44 dorab UCLA $ (Exp)";
  23. #endif
  24.  
  25. #include <stdio.h>        /* for obvious reasons */
  26. #include <a.out.h>        /* for obvious reasons */
  27. #include <sys/types.h>        /* for caddr_t */
  28. #include <strings.h>        /* for strlen */
  29.  
  30. /*
  31.  * dont turn this on unless you want copious debugging.
  32.  * it may also have unwanted interactions with sbrk.
  33.  */
  34. #undef DEBUG
  35.  
  36. /*
  37.  * alloca is used by default for efficiency. if you need to use
  38.  * malloc, then define USE_MALLOC
  39.  */
  40. /* #undef USE_MALLOC */
  41. #define USE_MALLOC
  42.  
  43. /* forward declarations */
  44. caddr_t sbrk();
  45. char *sprintf();
  46. #ifdef USE_MALLOC
  47. char *malloc();
  48. #else ~USE_MALLOC
  49. char *alloca();
  50. #endif ~USE_MALLOC
  51.  
  52. /*
  53.  * loadhelp takes an object file (objFile), and loads it
  54.  * into the current process, using relocation information found in the
  55.  * namelist of relocFile. In the process, it will create
  56.  * tmpFile, which has all the current relocation info and which can
  57.  * be used for a subsequent load. In addition, libString
  58.  * is used to search any required libraries.
  59.  * otherString can be used for other ld arguments.
  60.  * Returns 0 if all ok, >0 otherwise.
  61.  * It closes all files it has opened and unlinks the temp file
  62.  * if there has been an error.
  63.  * 
  64.  * TODO:
  65.  * do i need to round up the text/data sizes to word boundaries ?
  66.  */
  67.  
  68. /*
  69.  * the sprintf string for the ld command
  70.  * if this changes, also modify the code for ldCmdSpace
  71.  */
  72. #define LoadCommandTemplate "/bin/ld -N -x -A %s -T %lx %s %s -o %s %s -lc"
  73.  
  74. int
  75. loadhelp(objFile, relocFile, tmpFile, libString, otherString)
  76. char *objFile, *relocFile, *tmpFile, *libString, *otherString;
  77. {
  78. char *loadCommand;        /* pointer to string containing the ld cmd */
  79. int ldCmdSpace;            /* space allocated for ld command */
  80. char buf[BUFSIZ];        /* for buffering tmpFile i/o */
  81. struct exec hdr;
  82. long loadPoint, endOfMem, pageSize, tmp;
  83. FILE *tmpFD = NULL;
  84. long bytesToRead, bytesToExtend;
  85.  
  86. /*
  87.  * calculate the length of the ld command and allocate memory for it
  88.  * this code would need changing if LoadCommandTemplate was changed
  89.  */
  90. ldCmdSpace = strlen(LoadCommandTemplate);
  91. ldCmdSpace += strlen(objFile) + strlen(relocFile) + strlen(tmpFile);
  92. ldCmdSpace += strlen(libString) + strlen(otherString);
  93. ldCmdSpace += 16;    /* 10 for loadPoint + 1 for null + fudge of 5 */
  94.  
  95. #ifdef DEBUG
  96. (void)fprintf(stderr,"loadhelp: ld cmd needs %d bytes\n", ldCmdSpace);
  97. #endif DEBUG
  98.  
  99. #ifdef USE_MALLOC
  100. loadCommand = malloc((unsigned)ldCmdSpace);
  101. #else ~USE_MALLOC
  102. loadCommand = alloca(ldCmdSpace);
  103. #endif ~USE_MALLOC
  104.  
  105. if ((long)loadCommand == 0) {
  106. #ifdef DEBUG
  107.     perror("loadhelp");
  108.     (void)fprintf(stderr,
  109.               "loadhelp: could not allocate %d bytes for ld cmd\n",
  110.               ldCmdSpace);
  111. #endif DEBUG
  112. #ifdef USE_MALLOC
  113.     free(loadCommand);
  114. #endif USE_MALLOC
  115.     return(1);
  116.     }
  117.  
  118. pageSize = (long) getpagesize(); /* works on vaxen and suns */
  119. /* there is a strong assumption that pageSize is a power of 2 */
  120.  
  121. #ifdef DEBUG
  122. (void)fprintf(stderr,"loadhelp: page size is %ld (%lx)\n", pageSize, pageSize);
  123. #endif DEBUG
  124.  
  125. endOfMem = (long) sbrk(0); /* get end of current memory */
  126. if (endOfMem < 0) {
  127. #ifdef DEBUG
  128.     perror("loadhelp");
  129.     (void)fprintf(stderr,"loadhelp: sbrk(0) failed\n");
  130. #endif DEBUG
  131. #ifdef USE_MALLOC
  132.     free(loadCommand);
  133. #endif USE_MALLOC
  134.     return(2);
  135.     }
  136.  
  137. #ifdef DEBUG
  138. (void)fprintf(stderr,"loadhelp: end of memory = %ld (%lx)\n",
  139.                 endOfMem, endOfMem);
  140. #endif DEBUG
  141.  
  142. /* round up to the next higher pageSize */
  143. loadPoint = (long) sbrk((int)(pageSize - (endOfMem & (pageSize - 1L))));
  144.  
  145. if (loadPoint < 0L) {
  146. #ifdef DEBUG
  147.     perror("loadhelp");
  148.     (void)fprintf(stderr,"loadhelp: could not bump upto pagesize\n");
  149. #endif DEBUG
  150. #ifdef USE_MALLOC
  151.     free(loadCommand);
  152. #endif USE_MALLOC
  153.     return(3);
  154.     }
  155.  
  156. loadPoint = (long) sbrk(0);
  157. /*
  158.  * there had better be no further calls to sbrk explicitly or implicitly
  159.  * (e.g. via calling printf or something like that) until the loading is
  160.  * over.
  161.  */
  162.  
  163. /* sanity check */
  164. if (loadPoint < 0L || ((loadPoint & (pageSize - 1L)) != 0L)) {
  165. #ifdef DEBUG
  166.     perror("loadhelp");
  167.     (void)fprintf(stderr,"loadhelp: not page aligned\n");
  168. #endif DEBUG
  169. #ifdef USE_MALLOC
  170.     free(loadCommand);
  171. #endif USE_MALLOC
  172.     return(4);
  173.     }
  174.  
  175. #ifdef DEBUG
  176. (void)fprintf(stderr,"loadhelp: load point is %ld (%lx)\n",
  177.                 loadPoint, loadPoint);
  178. #endif DEBUG
  179.  
  180. (void)sprintf(loadCommand, LoadCommandTemplate,
  181.     relocFile, loadPoint, otherString, objFile, tmpFile, libString);
  182.  
  183. /* if the sprintf overflows it'll probably botch BAD, but just in case */
  184. if (strlen(loadCommand) >= ldCmdSpace) {
  185. #ifdef DEBUG
  186.     (void)fprintf(stderr,
  187.               "loadhelp: load command greater than %d byte buffer\n",
  188.               ldCmdSpace);
  189. #endif DEBUG
  190. #ifdef USE_MALLOC
  191.     free(loadCommand);
  192. #endif USE_MALLOC
  193.     return(5);
  194.     }
  195.  
  196. #ifdef DEBUG
  197. (void)fprintf(stderr,"loadhelp: the load command is \"%s\"\n", loadCommand);
  198. #endif DEBUG
  199.  
  200. /* run the ld comand to do relocation */
  201. if (system(loadCommand) != 0 ) {
  202. #ifdef DEBUG
  203.     perror("loadhelp");
  204.     (void)fprintf(stderr,"loadhelp: error in executing the ld command\n");
  205. #endif DEBUG
  206. #ifdef USE_MALLOC
  207.     free(loadCommand);
  208. #endif USE_MALLOC
  209.     return(6);
  210.     }
  211.  
  212. /* open the relocated file */
  213. tmpFD = fopen(tmpFile, "r");
  214. if (tmpFD == NULL ) {
  215. #ifdef DEBUG
  216.     perror("loadhelp");
  217.     (void)fprintf(stderr, "loadhelp: could not open %s for read\n",
  218.                   tmpFile);
  219. #endif DEBUG
  220. #ifdef USE_MALLOC
  221.     free(loadCommand);
  222. #endif USE_MALLOC
  223.     return(7);
  224.     }
  225.  
  226. /*
  227.  * use buf to buffer tmpFile so that no mallocs can occur
  228.  * since buf is automatic, tmpFD must be closed upon exit from this routine
  229.  */
  230. (void)setbuf(tmpFD,buf);
  231.  
  232. /* read its header */
  233. if (fread((char *)&hdr, sizeof(struct exec), 1, tmpFD) != 1) {
  234. #ifdef DEBUG
  235.     perror("loadhelp");
  236.     (void)fprintf(stderr,"loadhelp: error reading header of %s\n", tmpFile);
  237.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  238.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  239. #else ~DEBUG
  240.     (void)fclose(tmpFD);    /* close tmp file */
  241.     (void)unlink(tmpFile);    /* remove it */
  242. #endif ~DEBUG
  243. #ifdef USE_MALLOC
  244.     free(loadCommand);
  245. #endif USE_MALLOC
  246.     return(8);
  247.     }
  248.  
  249. if (N_BADMAG(hdr)) {
  250. #ifdef DEBUG
  251.     (void)fprintf(stderr,"loadhelp: bad magic number %o in %s\n",
  252.                   hdr.a_magic, tmpFile);
  253.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  254.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  255. #else ~DEBUG
  256.     (void)fclose(tmpFD);    /* close tmp file */
  257.     (void)unlink(tmpFile);    /* remove it */
  258. #endif ~DEBUG
  259. #ifdef USE_MALLOC
  260.     free(loadCommand);
  261. #endif USE_MALLOC
  262.     return(9);
  263.     }
  264.  
  265. #ifdef DEBUG
  266. (void)fprintf(stderr,
  267.   "loadhelp: magic = %o, text = %ld(%lx), data = %ld(%lx), bss = %ld(%lx)\n",
  268.                hdr.a_magic, hdr.a_text,
  269.                hdr.a_text, hdr.a_data,
  270.                hdr.a_data, hdr.a_bss, hdr.a_bss);
  271. #endif DEBUG
  272.  
  273. bytesToRead = hdr.a_text + hdr.a_data;
  274. bytesToExtend = bytesToRead + hdr.a_bss;
  275.  
  276. #ifdef DEBUG
  277. (void)fprintf(stderr,
  278.           "loadhelp: going to read %ld bytes and extend by %ld bytes\n",
  279.                bytesToRead, bytesToExtend);
  280. #endif DEBUG
  281.  
  282. /* get required memory */
  283. tmp = (long) sbrk((int)bytesToExtend);
  284. if (tmp < 0L) {
  285. #ifdef DEBUG
  286.     perror("loadhelp");
  287.     (void)fprintf(stderr,"loadhelp: not enough memory\n");
  288.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  289.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  290. #else ~DEBUG
  291.     (void)fclose(tmpFD);    /* close tmp file */
  292.     (void)unlink(tmpFile);    /* remove it */
  293. #endif ~DEBUG
  294. #ifdef USE_MALLOC
  295.     free(loadCommand);
  296. #endif USE_MALLOC
  297.     return(10);
  298.     }
  299.  
  300. /* some last sanity checks */
  301. if (tmp != loadPoint) {
  302. #ifdef DEBUG
  303.     (void)fprintf(stderr,
  304.               "loadhelp: load point is %ld but sbrk returns %ld\n",
  305.                   loadPoint, tmp);
  306.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  307.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  308. #else ~DEBUG
  309.     (void)fclose(tmpFD);    /* close tmp file */
  310.     (void)unlink(tmpFile);    /* remove it */
  311. #endif ~DEBUG
  312. #ifdef USE_MALLOC
  313.     free(loadCommand);
  314. #endif USE_MALLOC
  315.     return(11);
  316.     }
  317.  
  318. if (tmp & (pageSize - 1L)) {
  319. #ifdef DEBUG
  320.     (void)fprintf(stderr,
  321.               "loadhelp: allocated memory at %ld -not page aligned\n");
  322.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  323.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  324. #else ~DEBUG
  325.     (void)fclose(tmpFD);    /* close tmp file */
  326.     (void)unlink(tmpFile);    /* remove it */
  327. #endif ~DEBUG
  328. #ifdef USE_MALLOC
  329.     free(loadCommand);
  330. #endif USE_MALLOC
  331.     return(12);
  332.     }
  333.  
  334. /* go to beginning of text */
  335. if (fseek(tmpFD,(long)N_TXTOFF(hdr),0) < 0) {
  336. #ifdef DEBUG
  337.     perror("loadhelp");
  338.     (void)fprintf(stderr,"loadhelp: fseek failed on %s\n", tmpFile);
  339.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  340.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  341. #else ~DEBUG
  342.     (void)fclose(tmpFD);    /* close tmp file */
  343.     (void)unlink(tmpFile);    /* remove it */
  344. #endif ~DEBUG
  345. #ifdef USE_MALLOC
  346.     free(loadCommand);
  347. #endif USE_MALLOC
  348.     return(13);
  349.     }
  350.  
  351. /* read the text and data segments in */
  352. if (fread((char *)loadPoint, 1, (int)bytesToRead, tmpFD) != (int)bytesToRead) {
  353. #ifdef DEBUG
  354.     perror("loadhelp");
  355.     (void)fprintf(stderr, "loadhelp: could not read data from %s\n",
  356.                   tmpFile);
  357.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  358.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  359. #else ~DEBUG
  360.     (void)fclose(tmpFD);    /* close tmp file */
  361.     (void)unlink(tmpFile);    /* remove it */
  362. #endif ~DEBUG
  363. #ifdef USE_MALLOC
  364.     free(loadCommand);
  365. #endif USE_MALLOC
  366.     return(14);
  367.     }
  368.  
  369. #ifdef DEBUG
  370. if (fclose(tmpFD) == EOF) perror("loadhelp");
  371. #else ~DEBUG
  372. (void)fclose(tmpFD);
  373. #endif ~DEBUG
  374.  
  375. #ifdef USE_MALLOC
  376. free(loadCommand);
  377. #endif USE_MALLOC
  378.  
  379. return(0);
  380. }
  381.  
  382.  
  383. /*
  384.  * return the address of the function functionName in the namelist 
  385.  * of the file fileName.
  386.  * the calling procedure had better make sure that fileName exists.
  387.  */
  388. unsigned long
  389. nlistone(fileName,functionName)
  390. char *fileName, *functionName;
  391. {
  392. struct nlist nl[2];
  393. int rc;
  394.  
  395. nl[1].n_un.n_name = '\0'; /* terminate the name list */
  396. nl[0].n_un.n_name = functionName; /* put the function name in */
  397. rc = nlist(fileName,nl); /* call nlist */
  398. if (rc < 0 || (nl[0].n_type == (unsigned char) 0 /* check for errors */
  399.        && nl[0].n_value == (unsigned long) 0))
  400.     return ((unsigned long) 0);
  401. if (nl[0].n_type & N_TEXT) /* if it is in the text segment i.e. is a function */
  402.     return(nl[0].n_value); /* return the address */
  403. else
  404.     return ((unsigned long) 0); /* not a function */
  405. }
  406.